package com.algo.FJSP.GaForFJSP;

import com.algo.FJSP.common.DataManage;
import com.algo.FJSP.common.Operation;
import com.algo.FJSP.common.ScheduleResult;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: guoxing
 * @Email: gx_study2022@163.com
 * @Description:  写入写出数据工具类
 * @Date: 2024/7/3 22:38
 * @ClassName: ProcessDataUtils
 **/
public class ProcessDataUtils {


    /**
     * @Description 读取数据转换为可用的数据类型
     * @author guoxing
     * @date 2024/7/3 23:20
     * @param filePath
     * @return DataManage
     */
    public DataManage readFileToJobList(String filePath)  throws IOException {
        List<String> lines=new LinkedList<>(Files.readAllLines(Paths.get(filePath)));
        //去除空行
        lines.removeIf(line->line.trim().replace(" ","").isEmpty());
        String firstLine = lines.remove(0).replace("\t"," ").replace("   "," ").replace("  ", " ");
        //获取作业数、机器数、工序数
        String[] jobNumAndMachineNum=firstLine.split(" ");
        //工件数
        int jobNum=Integer.parseInt(jobNumAndMachineNum[0]);
        //机器数
        int machineNum=Integer.parseInt(jobNumAndMachineNum[1]);
        // 初始化用于存储工序和可选机器列表以及工序处理时间的映射
        //工序Oij 例如1-2就是第一个工件的第二道工序,以及可以选用的机器编号，所有可加工的设备
        Map<String,List<Integer>> operationAndMachineListMap=new HashMap<String,List<Integer>>();
        //机器k处理工序Oij所用的时间，i-j-k：T 例如2-1-3：4表示工序21在机器3上的加工时间为4
        Map<String,Integer> operationProcessTimeMap=new HashMap<String,Integer>();
        // 解析剩余的行，这些行定义了每个作业的工序细节
        //取出除了第一行之外的所有数字
        List<ArrayList<Integer>> collect = lines.stream()
                .map(line -> line.trim().replace("   "," ").replace("  ", " ").replace("\t"," ").split(" "))
                .map(arr -> {
                    ArrayList<Integer> list = new ArrayList<>(arr.length);
//                    System.out.println(Arrays.toString(arr));
                    for (String s : arr) {
//                        System.out.println(s);
                        list.add(Integer.parseInt(s));
                    }
                    return list;
                }).collect(Collectors.toList());
        // 初始化用于存储所有工序代码的列表
        List<String> operations=new ArrayList<>();
        for (int i = 0; i < collect.size(); i++) {
            int j=1;
            int operationOrder=0;
            while (j<collect.get(i).size()) {
                // 构造工序代码
                String operationCode=i+"-"+operationOrder;
                // 获取当前工序适用的机器数量
                int machineNumForOperation=collect.get(i).get(j);
                // 初始化工序的机器列表
                operationAndMachineListMap.put(operationCode,new ArrayList<>((machineNumForOperation)));
                operations.add(operationCode);
                // 遍历并记录每个工序在每台机器上的处理时间
                for (int k=j+1;k<j+1+machineNumForOperation*2;k+=2){
                    //k是机器编号，K+1是工序在这台设备上的处理时间
                    operationAndMachineListMap.get(operationCode).add(collect.get(i).get(k)-1);
                    operationProcessTimeMap.put(operationCode+"-"+(collect.get(i).get(k)-1),collect.get(i).get(k+1));
                }
                j+=(machineNumForOperation*2)+1;
                operationOrder++;
            }
        }
        // 创建并初始化 DataManage 对象
        Map<String,Integer> operationCodeAndIndexMap=new HashMap<>(operations.size());
        for (int i = 0; i < operations.size(); i++) {
            operationCodeAndIndexMap.put(operations.get(i),i);
        }
        DataManage DM=new DataManage();
        DM.setJobNum(jobNum);
        DM.setMachineNum(machineNum);
        DM.setOperationNum(operations.size());
        DM.setOperations(operations);
        DM.setOperationCodeAndMachineListMap(operationAndMachineListMap);
        DM.setOperationProcessTimeMap(operationProcessTimeMap);
        DM.setOperationCodeAndIndexMap(operationCodeAndIndexMap);
        System.out.println(DM.toString());
        return DM;

    }


    public void writeSchedule(String filepath, ScheduleResult scheduleResult) throws IOException {
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < scheduleResult.getMachines().size(); i++) {
            for (Operation operation : scheduleResult.getMachines().get(i).getOperations()) {
                content.append("(")
                        .append(operation.getCode())
                        .append(",")
                        .append(operation.getReleaseTime())
                        .append(",")
                        .append(operation.getCompleteTime())
                        .append(")");
            }
            if(i!=scheduleResult.getMachines().size()-1){
                content.append("|");
            }
        }
        Files.writeString(Paths.get(filepath),content);

    }

    public static void main(String[] args) {
        String path="D:\\GXprogram\\Doc\\algo\\src\\main\\java\\com\\algo\\FJSP\\GaForFJSP\\ex\\mk10.fjs";
        ProcessDataUtils p=new ProcessDataUtils();
        try {
            p.readFileToJobList(path);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
